<button id="btn">click</button>
<script>
    // 'use strict'

    const btn = document.getElementById('btn')
    btn.onclick = function () {
        console.log('click', this)
        // this 上下文
    }
    const obj = {
        name: 'obj1',
        onclick: function () {
            console.log('click', this)
        }
    }
    btn.onclick = obj.onclick.bind(obj) // 返回function
    obj.onclick()

    /*
    function 声明的函数this的指向：
    1. 会变（不固定）
    2. 根据上下文的调用改变
        - 当没有上下文调用的时候，并且js不按严格模式运行，
            this指向环境里的全局顶级对象(浏览器环境window)
    */
    function fn() {
        console.log(this)
    }
    fn() // 调用的时候没有上下文，a.fn()上下文就是a
    // window
    const o1 = { name: 'o1' }
    o1.f = fn
    o1.f() // 上下文是o1，this = o1
    const o2 = { name: 'o2' }
    o2.f = fn
    o2.f() // 上下文是o2，this = o2
    const o3 = { name: 'o3', sub: { name: 'sub', f: fn } }
    o3.sub.f() // 上下文是o3.sub, this=o3.sub
    fn.call(o1) // this=o1
    fn.call(o3) // this=o3
    const o4 = { name: 'o4' }
    fn.call(o4) // this=o4
    fn.call(null) // 非严格模式下 this=window
    const fn2 = fn.bind(o4) // bind绑定，返回一个新函数，
    // 里面的this固定
    fn2() // 没有上下文，this=o4
    o1.f2 = fn2
    o1.f2() // 上下文是o1，因为fn2的this固定为o4，this=o4
    fn2.call(o2) // this=o4
    const fn3 = fn2.bind(o1) // fn3的this=o4
    /*
    箭头函数的this指向：
    1. this是固定的（一旦箭头函数声明了this就不会变）
    2. this是它当时声明环境的this
        （出生的环境里的this当成自己的this）
    箭头函数和普通function的区别
    1. 箭头函数的this是固定的，function的this是随调用上下文改变
    2. 箭头函数不能当成构造方法使用
    3. 箭头函数里没有arguments对象（用...取不定个数的参数）
    */
    const fn4 = () => {
        console.log(this)
    }
    fn4() // this=window
    fn4.call(o4) // this=window

</script>